home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
PROGRAM
/
PCW_C.ARJ
/
LMENU.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-12-21
|
19KB
|
354 lines
/**********************************************************/
/* File Id. Lmenu.C */
/* Author. Stan Milam. */
/* Date Written. 05/08/89. */
/* */
/* (c) Copyright 1989, 1990 by Stan Milam */
/* */
/* Comments: The routines in this file allow the creation*/
/* and use of Lotus style menus. Moreover, more than one */
/* Lotus menu per window is allowed. More than one menu */
/* can be stacked into one window. The Mouse can be used */
/* to make selection and scroll the menus or the arrow & */
/* PgDn/PgUp keys can be used. Home & End keys move to */
/* first and last menus respectively. */
/**********************************************************/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <conio.h>
#include "pcw.i"
#include "pcwproto.h"
#include "menu.h"
#include "keys.h"
#define MSGROW 2
#define ITEMROW 1
/* Prototype the internal functions */
static void change_menu(LMNUTYPE *menu);
static void change_bar_pos(LMNUTYPE *menu, int crnt_bar);
static int search_menu(LMNUTYPE *menu, int select_char);
static int search_mouse_select(LMNUTYPE *menu, int col);
static int get_max_bars(LMNUFLDS *ltmp);
/***********************************************************/
/* Makelmenu */
/* */
/* This function when invoked will draw the Lotus menu */
/* pointed to by *menu. See the LMNUTYPE definition in */
/* menu.h. */
/***********************************************************/
WNDPTR *makelmenu(LMNUTYPE *menu) {
MENU_WND *lwnd; /* Pointer to menu window */
lwnd = &menu->lwnd; /* Establish adressablity */
setborder(lwnd->btype); /* Set borders & colors */
titlecolor(lwnd->tfclr, lwnd->tbclr);
bordercolor(lwnd->bfclr, lwnd->bbclr);
lwnd->wnd = wframe(lwnd->urow, lwnd->ucol, /* Frame the menu window */
lwnd->lrow, lwnd->lcol, /* and store handle in */
lwnd->fcolor, lwnd->bcolor); /* menu structure */
if (lwnd->wnd == NULL) return(NULL); /* Check to see of okay */
lwnd->urow = lwnd->wnd->urow; /* Wframe may have */
lwnd->ucol = lwnd->wnd->ucol; /* adjusted boundries */
lwnd->lrow = lwnd->wnd->lrow;
lwnd->lcol = lwnd->wnd->lcol;
qputchar(lwnd->urow+1,lwnd->ucol,lwnd->bfclr,lwnd->bbclr,24); /* Draw the arrows */
qputchar(lwnd->urow+1,lwnd->lcol,lwnd->bfclr,lwnd->bbclr,25);
wtitle(lwnd->wnd, lwnd->tvloc, lwnd->thloc, lwnd->title); /* Title wnd */
change_menu(menu); /* Fill window with menu */
return(lwnd->wnd); /* Contents & return */
}
/***********************************************************/
/* LmenuInput */
/* */
/* When invoked will manipulate Lotus menu. Returns the */
/* select_key in the LMNUFLDS. */
/***********************************************************/
int lmenuinput(LMNUTYPE *menu) {
LMNUFLDS *ltmp, **stmp; /* Pointers to menus */
MENU_WND *lwnd; /* Pointer the menu parms */
int ch; /* For keyin() function */
int max_bars, max_menus; /* How many menus & bars */
int crnt_wnd, crnt_bar; /* Keep track menus & bars */
int row, col, bstatus; /* For Mouse */
stmp = (LMNUFLDS **) menu->llist;
ltmp = stmp[menu->wnd_pos]; /* Get address of 1st menu */
lwnd = &menu->lwnd; /* Get address of wnd parms */
if (mpresent) hide_mouse(); /* Turn the mouse off so */
re_order(lwnd->wnd,NORMAL); /* We can reorder the windows */
if (mpresent) show_mouse(); /* And finally turn it on */
for (max_menus = 0;stmp[max_menus] != NULL;max_menus++);
max_menus--; /* and adjust */
max_bars = get_max_bars(ltmp); /* Get # selects this menu */
if (mpresent) show_mouse(); /* Turn on the mouse */
for(;;) { /* Loop forever */
crnt_bar = menu->bar_pos; /* Track current bar pos */
crnt_wnd = menu->wnd_pos; /* And menu position */
ch = keyin();
switch (ch) { /* Which one? */
case RITE_MOUSE_KEY :
case ESC: return(ESC); /* Wants to quit! */
case BOTH_MOUSE_KEY :
case ENTER : /* Selects bar pos */
return(ltmp[menu->bar_pos].select_key);
case LEFT_MOUSE_KEY :
get_mpos(&row, &col, &bstatus); /* Get row, col, button stat */
if (row == lwnd->wnd->urow+1) { /* Select row? */
if (search_mouse_select(menu, col)) { /* If hot spot */
change_bar_pos(menu,crnt_bar); /* Change */
return(ltmp[menu->bar_pos].select_key); /* return */
}
else {
if (col == lwnd->wnd->ucol) { /* Up arrow? */
menu->wnd_pos--; /* Decrement menu index */
if (menu->wnd_pos < 0) /* Check if okay */
menu->wnd_pos = max_menus; /* No - last menu */
menu->bar_pos = 0; /* First bar pos */
change_menu(menu); /* Next menu */
ltmp = stmp[menu->wnd_pos]; /* Address new menu */
max_bars = get_max_bars(ltmp); /* # bars new menu */
}
else { /* Down arrow */
if (col == lwnd->wnd->lcol) {
menu->wnd_pos++;
if (stmp[menu->wnd_pos] == NULL)
menu->wnd_pos = 0;
menu->bar_pos = 0;
change_menu(menu);
ltmp = stmp[menu->wnd_pos];
max_bars = get_max_bars(ltmp);
}
}
}
}
break;
case LEFTARROW : /* Prev bar pos */
case SHFTTAB :
menu->bar_pos--;
if (menu->bar_pos < 0) /* Check if < 0 */
menu->bar_pos = max_bars; /* Set to max bar */
change_bar_pos(menu, crnt_bar); /* Change bar poisition */
break;
case RITEARROW : /* Next bar position */
case TAB :
menu->bar_pos++; /* Bump & check */
if (ltmp[menu->bar_pos].select_key == '\0')
menu->bar_pos = 0; /* First one if at end */
change_bar_pos(menu, crnt_bar); /* Change bars */
break;
case UPARROW : /* Prev Menu */
case PGUP:
if (max_menus == 0) break;
menu->wnd_pos--; /* Decrement menu index */
if (menu->wnd_pos < 0) menu->wnd_pos = max_menus;
menu->bar_pos = 0; /* Set bar index to first */
change_menu(menu); /* Put out new menu */
ltmp = stmp[menu->wnd_pos]; /* Address new menu */
max_bars = get_max_bars(ltmp); /* Count its selections */
break;
case DOWNARROW : /* Next menu */
case PGDN:
if (max_menus == 0) break;
menu->wnd_pos++; /* Bump menu index */
if (stmp[menu->wnd_pos] == NULL) /* See if at end */
menu->wnd_pos = 0; /* And set to first */
menu->bar_pos = 0; /* First bar of menu */
change_menu(menu); /* Put out new menu */
ltmp = stmp[menu->wnd_pos]; /* Address new menu */
max_bars = get_max_bars(ltmp); /* Count the selects */
break;
case HOME : /* First menu */
if (menu->wnd_pos == 0) break;
menu->bar_pos = menu->wnd_pos = 0;
change_menu(menu);
ltmp = stmp[0];
max_bars = get_max_bars(ltmp);
break;
case END: /* Last Menu */
if (menu->wnd_pos == max_menus) break;
menu->bar_pos = 0;
menu->wnd_pos = max_menus;
change_menu(menu);
ltmp = stmp[menu->wnd_pos];
max_bars = get_max_bars(ltmp);
break;
default :
if (search_menu(menu, ch)) { /* Search for select match */
if (crnt_wnd != menu->wnd_pos) { /* In another menu? */
change_menu(menu); /* Put out new menu */
ltmp = stmp[menu->wnd_pos]; /* Address new menu */
return(ltmp[menu->bar_pos].select_key); /* Return */
}
if (crnt_bar != menu->bar_pos) { /* Same menu,another bar */
change_bar_pos(menu, crnt_bar); /* Chg bar pos */
return(ltmp[menu->bar_pos].select_key); /* Return */
}
else /* Must be crnt bar */
return(ltmp[menu->bar_pos].select_key); /* So Return */
}
}
}
#ifndef __TURBOC__
return ( (char) 0 );
#endif
}
/***********************************************************/
/* Change_Menu */
/* */
/* When invoked puts menu pointed to by menu->wnd_pos in */
/* the window. Bar position is determined by menu->bar_pos*/
/***********************************************************/
static void change_menu(LMNUTYPE *menu) {
int lcv1, col, length;
LMNUFLDS *ltmp, **stmp;
MENU_WND *lwnd;
lwnd = &menu->lwnd;
stmp = (LMNUFLDS **) menu->llist;
ltmp = stmp[menu->wnd_pos];
if (mpresent) hide_mouse();
clr_wnd(lwnd->wnd, 1);
for (lcv1 = 0; ltmp[lcv1].select_key != (char) NULL; lcv1++)
wputs(lwnd->wnd, ITEMROW, ltmp[lcv1].select_col, ltmp[lcv1].item);
col = ltmp[menu->bar_pos].select_col;
length = strlen(ltmp[menu->bar_pos].item);
w_chg_attr(lwnd->wnd,ITEMROW, col, lwnd->cfclr, lwnd->cbclr, length);
wputs(lwnd->wnd, MSGROW, 2, ltmp[menu->bar_pos].item_msg);
if (mpresent) show_mouse();
}
/***********************************************************/
/* Search_Menu */
/* */
/* Searches thru all menus looking for a select_key match */
/* with keyboard input. All characters are converted to */
/* upper case. Returns non-zero if found. Zero if not */
/* found. If a match is found the menu index and bar index*/
/* are changed to point to the selected item. */
/***********************************************************/
static int search_menu(LMNUTYPE *menu, int select_char) {
LMNUFLDS *ltmp, **stmp; /* Menu Pointers */
int lcv1, lcv2, ch; /* Index variables */
stmp = (LMNUFLDS **) menu->llist; /* Address menu lists */
select_char = toupper(select_char); /* Uppercase keybd input */
for (lcv1 = 0; stmp[lcv1] != NULL; lcv1++) { /* Get the menu list */
ltmp = stmp[lcv1]; /* One menu list at a time */
for (lcv2 = 0; ltmp[lcv2].select_key != (char) NULL; lcv2++) {
ch = (char) toupper(ltmp[lcv2].select_key); /* Uppercase select_key */
if (ch == select_char) { /* Do they match ? */
menu->bar_pos = lcv2; /* Set bar index */
menu->wnd_pos = lcv1; /* Set menu index */
return(1); /* Return TRUE */
}
}
}
return (0); /* No matches */
}
/**********************************************************/
/* Search_Mouse_Select */
/* */
/* Runs through all items in a menu to determine if the */
/* rat was on the item. If a match is found the bar index*/
/* is updated to reflect the selected item and we return */
/* a non-zero return code to indicate a match was found. */
/**********************************************************/
static int search_mouse_select(LMNUTYPE *menu, int col) {
MENU_WND *lwnd;
LMNUFLDS *ltmp, **stmp;
int lcv, item_len, item_col;
lwnd = &menu->lwnd; /* Establish Addressability */
stmp = (LMNUFLDS **) menu->llist;
ltmp = stmp[menu->wnd_pos];
if (col > lwnd->wnd->ucol) col -= lwnd->wnd->ucol; /* If inside the window determine column in the window */
else return(0); /* Otherwise not in window so exit */
for (lcv = 0; ltmp[lcv].select_key != '\0'; lcv++) { /* Search thru all items in list */
item_col = ltmp[lcv].select_col; /* Get items column */
item_len = (item_col + strlen(ltmp[lcv].item)) - 1; /* Determine its length on the screen */
if (col >= item_col && col <= item_len) { /* If mouse on the item */
menu->bar_pos = lcv; /* Set the bar index */
return(1); /* Return True */
}
}
return(0); /* No match found */
}
/**********************************************************/
/* Change_Bar_Pos */
/* */
/* Changes the bar position in the window by changing the */
/* attribute of the current bar to normal window attribute*/
/* and changing the attribute of the new item to the color*/
/* specified for bar color. Got it. Okay, test in five */
/* minutes! */
/**********************************************************/
static void change_bar_pos(LMNUTYPE *menu, int crnt_bar) {
int row, col, length;
LMNUFLDS *ltmp, **stmp;
MENU_WND *lwnd;
lwnd = &menu->lwnd; /* Establish addressability */
stmp = (LMNUFLDS **) menu->llist;
ltmp = stmp[menu->wnd_pos];
if (mpresent) hide_mouse(); /* If rat home hide from neighbors! */
length = strlen(ltmp[crnt_bar].item); /* Get length of item on screen */
col = ltmp[crnt_bar].select_col; /* Get its column */
w_chg_attr(lwnd->wnd,ITEMROW,col,lwnd->fcolor,lwnd->bcolor,length);/* Change its color attribute */
length = strlen(ltmp[menu->bar_pos].item); /* Get length of new item */
col = ltmp[menu->bar_pos].select_col; /* Get its column */
w_chg_attr(lwnd->wnd,ITEMROW,col, lwnd->cfclr, lwnd->cbclr,length);/* Change its color attribute */
col = lwnd->wnd->ucol + 1; /* Now, must clear the message line */
row = lwnd->wnd->urow + 2;
length = (lwnd->wnd->lcol - 1) - col;
qhchar(row, col, lwnd->fcolor, lwnd->bcolor, 32, length); /* Clear the line */
wputs(lwnd->wnd, 2,2, ltmp[menu->bar_pos].item_msg); /* And write then new message */
if (mpresent) show_mouse(); /* Finally turn back on the mouse */
}
/**********************************************************/
/* Get_Max_Bars */
/* */
/* Used to count how many selections for a given menu. */
/**********************************************************/
static int get_max_bars(LMNUFLDS *ltmp) {
int i;
for (i = 0; ltmp[i].select_key != '\0'; i++); i--;
return(i);
}